/* 
 *	Copyright (C) 2009-2010 miaohua
 *	http://code.google.com/p/lrcshower/
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *  http://www.gnu.org/copyleft/gpl.html
 *
 */
#include "stdafx.h"
#include <fstream>
#include <string>
#include <memory>
#include <iterator>
#include "resource.h"
#include "Config.h"
#include "ParseErrCode.h"
#include "SearchEngineComHdr.h"
#include "BaiduMusic.h"
#include "BaiduLrcParser.h"
#include "BaiduPageParser.h"
#include "HelperFunctions.h"
#include "SimpleFileDownloader.h"
#include "SimpleWebPageParser.h"
#include "BaiduDecodeUrlHelperFunction.h"
#include "BaiduMusicImp.h"
using namespace std;

const int CBaiduMusicImp::m_SongNumPerPage = 30;
const TCHAR * CBaiduMusicImp::m_EngineName = _T("Baidu");

CBaiduMusicImp::CBaiduMusicImp():m_EngineLogo(IDB_BAIDU_LOGO)
{
     // Create the download
     m_Downloader = auto_ptr<IFileDownloader>(new CSimpleFileDownloader());

     // Create web page parser
     m_MusicWebPageParse = auto_ptr<IWebPageParse>(new CSimpleWebPageParser());
}


int CBaiduMusicImp::SearchSong(const tstring & Song, tstring & ErrMsg, SongList & List, int Page)
{
     if( Song.empty() )
     {
         ErrMsg = AppErrMsg[E_SongName_Empty];
         return -1;
     }

     m_SongName = Song;
     // Generate the get html baidu mp3 url
     tstring Url = BaiduMp3UrlGen(m_SongName, Page);

     // Now we use the memory cache not disk file
     tstring HtmlSrc;
     if( !m_Downloader->StartFileDownload(Url, HtmlSrc) )
     {
         ErrMsg = AppErrMsg[E_DownloadList_Fail];
         return -1;
     }
      
     // Regiser parsers
     m_MusicWebPageParse->RegisterParser(&m_SongParser);
     m_MusicWebPageParse->RegisterParser(&m_SongNumParser);

     // Do parse
     m_MusicWebPageParse->Parse(HtmlSrc);  

     // Clear registed parsers
     m_MusicWebPageParse->ClearParser();

     // Extract the song list
     m_SongParser.GetSongList(List);

     return List.size();
}

int CBaiduMusicImp::SearchLrc(const tstring & SongName, const tstring & Singer, tstring & ErrMsg, LrcList & List, int Page)
{
     if( SongName.empty() )
     {
         ErrMsg = AppErrMsg[E_SongName_Empty];
         return -1;
     }
     // Generate the get html baidu lrc url
     tstring Url = BaiduLrcUrlGen(SongName, Singer, Page);

     // Get the application's tmp directory & lrc file's full path
     // If in debug mode, we download the lrc file on harddisk;
     // If in release mode, we just download in memory
     tstring DataBuf;
#ifdef _DEBUG
     tstring TmpPath;
     if( !GetTmpDir(TmpPath, HTML_TMP_DIR) )
     {
         ErrMsg = AppErrMsg[E_GetTmpDir_Fail];
         return -1;
     }

     DataBuf = TmpPath + tstring(_T("\\")) + SongName + SONGLRC_EXT;
#endif
     // Download the song download url web page
     if( !m_Downloader->StartFileDownload(Url, DataBuf)  )
     {
         ErrMsg = AppErrMsg[E_DownloadList_Fail];
         return -1;
     }

     // Regex parse web page
     // Get the content of html page
     tstring HtmlSrc;
#ifdef _DEBUG
     ifstream in(DataBuf.c_str());
     string data((istreambuf_iterator<char>(in)), istreambuf_iterator<char>());
#ifdef UNICODE
     MultiBytes2WildStr(data, HtmlSrc);
#else
     HtmlSrc = data;
#endif
#else
     HtmlSrc = DataBuf;
#endif

     // Regiser parsers
     m_MusicWebPageParse->RegisterParser(&m_LrcParser);
     m_MusicWebPageParse->RegisterParser(&m_LrcNumParser);

     // Do parse
     m_MusicWebPageParse->Parse(HtmlSrc);  

     // Get result
     m_LrcParser.GetLrcList(List);

     // Clear parser
     m_MusicWebPageParse->ClearParser();

     return m_LrcParser.ResultCount();
}


bool CBaiduMusicImp::GetMp3DownloadUrl(int Idx, tstring & SongUrl)
{
     if( Idx >= m_SongParser.ResultCount() ) return false;

     // Get the song's download promt page url
     tstring Url = m_SongParser[Idx].url;
     // Download the promt page
     // In debug mode we download the webpage to local disk
     // But in release mode we download it to memroy
     tstring DataBuf;
#ifdef _DEBUG
     tstring FileName = m_SongName + IntToStr(Idx); 
     // Get the application's tmp directory
     tstring TmpPath;
     if( !GetTmpDir(TmpPath, HTML_TMP_DIR) )
     {
#ifdef _DEBUG
         _Dbg_Printf(AppErrMsg[E_GetTmpDir_Fail]);
#endif
         return false;
     }
     DataBuf = TmpPath + tstring(_T("\\")) + FileName + DOWNLOAD_URL_EXT; 
#endif
     // Download the song download url web page
     if( !m_Downloader->StartFileDownload(Url, DataBuf)  )
     {
#ifdef _DEBUG
         _Dbg_Printf(AppErrMsg[E_DownloadList_Fail]);
#endif
         return false;
     }
        
     tstring HtmlSrc;
#ifdef _DEBUG
     ifstream in(DataBuf.c_str());
     string Data((istreambuf_iterator<char>(in)), istreambuf_iterator<char>());
#ifdef UNICODE
     MultiBytes2WildStr(Data, HtmlSrc);
#else
     HtmlSrc = Data;
#endif
#else
     HtmlSrc = DataBuf;
#endif
     // Parser
     CBaiduSongUrlParser UrlParser;

     // Register parser
     m_MusicWebPageParse->RegisterParser(&UrlParser);
        
     // Do parse
     m_MusicWebPageParse->Parse(HtmlSrc);

     // Clear
     m_MusicWebPageParse->ClearParser();

     // If we are unable to get the file's down load url, then prompt to user
     if( UrlParser.DownloadUrl().empty() )
     {
#ifdef _DEBUG
         _Dbg_Printf(AppErrMsg[E_DownloadList_Fail]);
#endif
         return false;
     }      

     // Save the url
     SongUrl = UrlParser.DownloadUrl();
     return true;
}

bool CBaiduMusicImp::GetLrcDownloadUrl(int Idx, tstring & Url)
{
     if( Idx >= m_LrcParser.ResultCount() ) return false;

     Url = m_LrcParser[Idx].url;
     return true;
}

int CBaiduMusicImp::GetSongTotalNum()const
{
    return m_SongNumParser.TotalNum();
}

int CBaiduMusicImp::GetLrcTotalNum()const
{
    return m_LrcNumParser.TotalNum();
}

const TCHAR * CBaiduMusicImp::GetEngineName()const
{
     return m_EngineName;
}

bool CBaiduMusicImp::GetEngineLogo(HBITMAP & Logo)const 
{
      Logo = m_EngineLogo.GetHandler();
      // Check wether loading bitmap is successful
      if( Logo == NULL ) return false;
      return true;
}

extern CBaiduMusicImp * Gbl_BaiduMusicImp/* = new CBaiduMusicImp()*/;

const TCHAR*  __stdcall BaiduGetEngineName()
{
     return Gbl_BaiduMusicImp->GetEngineName();
}

bool  __stdcall BaiduGetEngineLogo(HBITMAP & Logo)
{
     return Gbl_BaiduMusicImp->GetEngineLogo(Logo);
}

int  __stdcall BaiduSearchSong(const tstring & songName, tstring & errMsg, SongList & List, int page)
{
     return Gbl_BaiduMusicImp->SearchSong(songName, errMsg, List, page);
}

int  __stdcall BaiduSearchLrc(const tstring & SongName, const tstring & Singer, tstring & ErrMsg, LrcList & List, int Page)
{
     return Gbl_BaiduMusicImp->SearchLrc(SongName, Singer, ErrMsg, List, Page);
}

bool  __stdcall BaiduGetMp3DownloadUrl(int Idx, tstring & Url)
{
     return Gbl_BaiduMusicImp->GetMp3DownloadUrl(Idx, Url);
}

bool  __stdcall BaiduGetLrcDownloadUrl(int Idx, tstring & Url)
{
     return Gbl_BaiduMusicImp->GetLrcDownloadUrl(Idx, Url);
}

int __stdcall  BaiduGetSongTotalNum()
{
     return Gbl_BaiduMusicImp->GetSongTotalNum();
}

int __stdcall  BaiduGetLrcTotalNum()
{
     return Gbl_BaiduMusicImp->GetLrcTotalNum();
}
